package com.ruoyi.store.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.flashpay.constant.CacheKey;
import com.ruoyi.common.core.flashpay.domain.TbOrder;
import com.ruoyi.common.core.flashpay.utils.IdWorker;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.store.domain.*;
import com.ruoyi.store.feign.CouponClient;
import com.ruoyi.store.feign.DishesClient;
import com.ruoyi.store.feign.OrderClient;
import com.ruoyi.store.vo.TbDishesVo;
import com.thoughtworks.xstream.XStream;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Controller
@RequestMapping("/wechat")
@CrossOrigin
public class WeChatController extends BaseController {

    @GetMapping("/message")
    @ResponseBody
    public Long message(String signature, String timestamp, String nonce, Long echostr) {
        System.out.println(signature + "-" + timestamp + "-" + nonce + "-" + echostr);
        return echostr;
    }


    @PostMapping("/message")
    @ResponseBody
    public String message(HttpServletRequest request) throws IOException, DocumentException {
        ServletInputStream inputStream = request.getInputStream();
        SAXReader saxReader = new SAXReader();
        Map<String, String> requestXML = new HashMap<>();
        Document document = saxReader.read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.elements();
        for (Element element : elements) {
            requestXML.put(element.getName(), element.getStringValue());
        }
        String msgType = requestXML.get("MsgType");
        String result = "";
        if (msgType.equals("text")) {
            String message = requestXML.get("Content");
            System.out.println("用户发送的消息为：" + message);
            result = "已收到您的消息";
        }
        ObjectMapper objectMapper = new ObjectMapper();
        if (msgType.equals("event")) {
            String codeMessage = requestXML.get("ScanCodeInfo");
            if (codeMessage == null) {
                return "";
            }
            String[] split = codeMessage.split("\\n");
            String json = split[1];
            Map codeMap = objectMapper.readValue(json, Map.class);
            result = "<a href='http://wechart.5gzvip.91tunnel.com/dishes.html?openId=" + requestXML.get("FromUserName") + "&storeId=" + codeMap.get("storeId") + "&tableId=" + codeMap.get("tableId") + "'>点击下单</a>";
        }
        WeChatTextResponse weChatTextResponse = new WeChatTextResponse();
        weChatTextResponse.setContent(result);
        weChatTextResponse.setCreateTime(System.currentTimeMillis() + "");
        weChatTextResponse.setToUserName(requestXML.get("FromUserName"));
        weChatTextResponse.setFromUserName(requestXML.get("ToUserName"));
        weChatTextResponse.setMsgType("text");
        XStream xStream = new XStream();
        xStream.alias("xml", WeChatTextResponse.class);
        String responseXML = xStream.toXML(weChatTextResponse);
        return responseXML;
    }

    @Autowired
    private CouponClient couponClient;

    @GetMapping(value = "/coupons")
    @ResponseBody
    public TableDataInfo list(TbCoupon tbCoupon) {
        TableDataInfo tableDataInfo = couponClient.list(tbCoupon);
        return tableDataInfo;
    }

    @GetMapping("/orderPage")
    public String orderPage(String code) throws IOException {
        Map jsonMap = getOpenId(code);
        return "redirect:http://wechart.5gzvip.91tunnel.com/order.html?openId=" + jsonMap.get("openid");
    }

    private Map getOpenId(String code) throws IOException {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx01cb0b0967195727&secret=6116762897ac990ee6dc300e07cc60d9&code=" + code + "&grant_type=authorization_code";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        String json = EntityUtils.toString(response.getEntity(), "UTF-8");
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(json, Map.class);
    }

    @GetMapping("couponPage")
    public String couponPage(String code) throws IOException {
        Map jsonMap = getOpenId(code);
        return "redirect:http://wechart.5gzvip.91tunnel.com/coupon.html?openId=" + jsonMap.get("openid");
    }

    @PutMapping(value = "/coupon/{couponId}/{openId}")
    @ResponseBody
    public AjaxResult receiveCoupon(@PathVariable("couponId") Long couponId, @PathVariable("openId") String openId) throws ParseException {
        return couponClient.receiveCoupon(couponId, openId);
    }

    @Autowired
    private DishesClient dishesClient;

    @GetMapping("/dishes")
    @ResponseBody
    public TableDataInfo list(TbDishes tbDishes) {
        return getDataTable(dishesClient.list(tbDishes));
    }

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/joinCar")
    @ResponseBody
    public AjaxResult joinShoppingCar(@RequestBody TbDishesVo tbDishesVo) {
        String key = CacheKey.getShoppingCarKey(tbDishesVo.getStoreId(), tbDishesVo.getTableId());
        List<TbDishesVo> tbDishesVoList = (List<TbDishesVo>) redisTemplate.opsForValue().get(key);
        if (null == tbDishesVoList) {
            tbDishesVoList = new ArrayList<>();
        }
        //集合大小>0  redis中存在数据
        if (tbDishesVoList.size() > 0) {
            for (TbDishesVo dishesVo : tbDishesVoList) {
                //存在只加入数量
                Long redisDishesId = dishesVo.getDishesId();
                if (redisDishesId.equals(tbDishesVo.getDishesId())) {
                    dishesVo.setCount(dishesVo.getCount() + tbDishesVo.getCount());
                    dishesVo.setTotalPrice(dishesVo.getDishesPrice().multiply(new BigDecimal(dishesVo.getCount())));
                    redisTemplate.opsForValue().set(key, tbDishesVoList);
                    return AjaxResult.success();
                }
            }
        }
        //redis中无数据   或   不存在相同的菜品直接进行添加
        tbDishesVo.setTotalPrice(tbDishesVo.getDishesPrice().multiply(new BigDecimal(tbDishesVo.getCount())));
        tbDishesVoList.add(tbDishesVo);
        redisTemplate.opsForValue().set(key, tbDishesVoList);
        return AjaxResult.success();
    }

    @GetMapping("/getCar")
    @ResponseBody
    public AjaxResult getShoppingCar(Long storeId, Long tableId) {
        String key = CacheKey.getShoppingCarKey(storeId, tableId);
        List<TbDishesVo> tbDishesVoList = (List<TbDishesVo>) redisTemplate.opsForValue().get(key);
        if(null ==tbDishesVoList){
            return AjaxResult.error("目前购物车中没有数据!");
        }
        BigDecimal sum = new BigDecimal(0);
        for (TbDishesVo tbDishesVo : tbDishesVoList) {
            sum = sum.add(tbDishesVo.getTotalPrice());
        }
        Map map = new HashMap();
        map.put("tbDishesVoList", tbDishesVoList);
        map.put("sum", sum);
        return AjaxResult.success(map);
    }

    @GetMapping("/myCoupon")
    @ResponseBody
    public AjaxResult selectMyCoupon(TbCouponRecord tbCouponRecord) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) couponClient.selectMyCoupon(tbCouponRecord).getRows();
        return AjaxResult.success(list);
    }

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @PostMapping("/commitOrder")
    @ResponseBody
    public AjaxResult commitOrder(@RequestBody TbOrder tbOrder, TbOrderDetail tbOrderDetail, Long[] couponIds) throws InterruptedException {
        //进行上锁 order  店铺ID  餐桌ID
        RLock rLock = redissonClient.getLock("order_" + tbOrder.getStoreId() + "_" + tbOrder.getTableId());
        try {
            rLock.tryLock(5,10, TimeUnit.SECONDS);
            //redis中是否存在该餐桌状态
            String usedTableKey="flashPay:usedTable:" + tbOrder.getStoreId() + ":" + tbOrder.getTableId();
            String status = (String) redisTemplate.opsForValue().get(usedTableKey);
            if(!Objects.isNull(status)){
                return AjaxResult.error("该餐桌还有未完成的订单,请等待!");
            }
            tbOrder.setOrderId(idWorker.nextId());
            //将订单信息缓存入redis中
            String orderKey = CacheKey.getOrderKey(tbOrder.getSikgaekId());
            redisTemplate.opsForHash().put(orderKey,String.valueOf(tbOrder.getOrderId()),tbOrder);
            //发送mq存储订单mysql数据  订单详情表      处理菜品json信息
            Map map = new HashMap();
            map.put("tbOrder", tbOrder);
            map.put("remark", tbOrderDetail.getRemark());
            rabbitTemplate.convertAndSend("order", map);
            // 修改优惠券领取记录状态  和  绑定的订单ID
            for (Long couponId : couponIds) {
                TbCouponRecord tbCouponRecord = new TbCouponRecord();
                tbCouponRecord.setUsedTime(new Date());
                tbCouponRecord.setCouponId(couponId);
                tbCouponRecord.setStatus(1L);
                tbCouponRecord.setOrderId(tbOrder.getOrderId());
                tbCouponRecord.setSikgaekId(tbOrder.getSikgaekId());
                couponClient.useCoupon(tbCouponRecord);
            }
            //存入redis 餐桌状态
            redisTemplate.opsForValue().set(usedTableKey,"1");
            return AjaxResult.success();
        } finally {
            if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                //3. 解锁
                rLock.unlock();
            }
        }
    }


}
